package examples.rrc;

import java.awt.*;
import java.applet.*;

//import MT.*;

/** RailRoadCrossing with visual simulation */
public class RRC extends Applet implements Runnable {
  // Simulation screen dependent
  static final int width = 900, height = 300;
  static final int rr_x = 0, rr_y = 100;// Upper Left corner of railroad
  static boolean working;
  static final int rr_width = width, rr_height = 100;
  static final int train_height = 60;
  static int train_length = 130;
  float train_x = 0 - train_length;
  int train_y = rr_y + 10;
  int time_unit, time_granularty;

  // Specification dependent
  int rr_length = width;
  int cross_x, cross_y;
  int cross_length, cross_height;
  int ni, ip, gamma, delta;
  int time_tolerant;

  // Simulation screen dependent II
  int gate_length, gate_center_x, gate_center_y;
  int gate_end_x, gate_end_y;

  // logical Time

  Thread animator = null;
  // FT ft= null;
  Train train = null;
  Gate gate = null;
  Controller controller = null;

  Image offscreen = null;
  boolean stop = true;
  long c_time, offset_time;
  int logical_time = 0;
  Graphics g_off, g;
  Image train_image = null, background_image = null, semaphore_image = null;
  boolean use_timed_event = true;

  public void init() {
    System.out.println(this.getDocumentBase());
    train_image = this.getImage(this.getDocumentBase(), 
        "train.gif");
    background_image = this.getImage(this.getDocumentBase(), 
        "map.gif");
    semaphore_image = this.getImage(this.getDocumentBase(), 
        "controller.gif");

    ni = Integer.parseInt(this.getParameter("ni"));
    ip = Integer.parseInt(this.getParameter("ip"));
    delta = Integer.parseInt(this.getParameter("delta"));
    gamma = Integer.parseInt(this.getParameter("gamma"));
    time_unit = Integer.parseInt(this.getParameter("time_unit"));
    time_granularty = Integer.parseInt(this.getParameter("time_granularty"));
    time_tolerant = Integer.parseInt(this.getParameter("time_tolerant"));
    use_timed_event = (Boolean.valueOf(this.getParameter("use_timed_event")))
        .booleanValue();
    // Specification dependent
    cross_x = ((rr_length + train_length) * ni) / (ni + ip + delta);
    cross_y = 0;
    cross_length = ((rr_length + train_length) * ip) / (ni + ip + delta)
        - train_length;
    cross_height = height;

    // Simulation screen dependent II
    gate_length = cross_length;
    gate_center_x = cross_x + cross_length;
    gate_center_y = rr_y + rr_height;
    gate_end_x = gate_center_x;
    gate_end_y = gate_center_y - gate_length;

  }

  public void start() {
    animator = new Thread(this);
    animator.setPriority(Thread.NORM_PRIORITY + 1);
    train = new Train(this);
    gate = new Gate(this);
    controller = new Controller(this);
  }

  public void paint(Graphics g) {
    drawBackground(g);
    g.drawImage(train_image, (int) train_x, train_y, this);
    g.drawImage(semaphore_image, cross_x + cross_length, rr_y - 30, this);

    g.drawLine(gate_center_x - 2, gate_center_y - 2, gate_end_x - 2,
        gate_end_y - 2);
    g.drawLine(gate_center_x - 1, gate_center_y - 1, gate_end_x - 1,
        gate_end_y - 1);
    g.drawLine(gate_center_x, gate_center_y, gate_end_x, gate_end_y);
    g.drawLine(gate_center_x + 1, gate_center_y + 1, gate_end_x + 1,
        gate_end_y + 1);
    g.drawLine(gate_center_x + 2, gate_center_y + 2, gate_end_x + 2,
        gate_end_y + 2);
  }

  public void run() {
    if (offscreen == null)
      offscreen = this.createImage(width, height);
    g = this.getGraphics();
    g_off = offscreen.getGraphics();

    while (true) {
      paint(g_off);
      g.drawImage(offscreen, 0, 0, this);

      try {
        Thread.sleep(time_granularty);
      } catch (InterruptedException e) {
      }
    }
  }

  public boolean mouseDown(Event e, int x, int y) {
    // System.out.println("Mouse down!");
    if (!working) {
      working = true;
      animator.start();
      gate.start();
      train.start();
      controller.start();

    }

    return true;
  }

  void drawBackground(Graphics g) {
    g.drawImage(background_image, 0, 0, this);
    g.setColor(Color.white);
    g.fillRect(rr_x, rr_y, rr_width, rr_height);
    g.fillRect(cross_x, cross_y, cross_length, cross_height);
    g.setColor(Color.black);
    g.drawRect(rr_x, rr_y, rr_width, rr_height);
    g.drawRect(cross_x, cross_y, cross_length, cross_height);

    // Draw 30 lines
    for (int i = 0; i <= rr_width; i += rr_width / 30)
      g.drawLine(rr_x + i, rr_y, rr_x + i, rr_y + rr_height);
  }
}
